package io.gitee.bowen_lee.rpc;

import java.net.InetSocketAddress;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * 客户端工厂
 * 
 * @author Bowen
 * @since 2022-01-18 15:38:32
 */
public class BowenClientFacory {

  private static int clientXPoolSize;

  Random rand = new Random();

  ConcurrentHashMap<InetSocketAddress, BowenClientPool> outboxs = new ConcurrentHashMap<>();

  static BowenClientFacory clientFactory;

  static {
    clientFactory = new BowenClientFacory();
  }

  public static BowenClientFacory getFactory() {

    return clientFactory;
  }

  public synchronized NioSocketChannel getclient(InetSocketAddress inetSocektAddress) {
    BowenClientPool clientPool = outboxs.get(inetSocektAddress);
    if (clientPool == null) {
      outboxs.put(inetSocektAddress, new BowenClientPool(clientXPoolSize));
      clientPool = outboxs.get(inetSocektAddress);
    }
    // 用算法(此处随机取值) 获取一个连接池下标
    int index = rand.nextInt(clientXPoolSize);
    if (clientPool.getClient(index) != null && clientPool.getClient(index).isActive()) {
      return clientPool.getClient(index);
    } else {
      // 没有连接 说明是第一次进来. 创建channel连接 (正常项目中,我觉得应该是在启动项目的时候进行饿汉式创建)
      synchronized (clientPool.lock[index]) {
        return clientPool.clients[index] = create(inetSocektAddress);
      }
    }
  }

  /**
   * 创建 NioSocketChannel
   * 
   * @param inetSocektAddress 服务端地址
   * @return
   */
  private NioSocketChannel create(InetSocketAddress inetSocektAddress) {
    NioEventLoopGroup loopGroup = new NioEventLoopGroup();

    Bootstrap bs = new Bootstrap();
    bs.group(loopGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<NioSocketChannel>() {

      @Override
      protected void initChannel(NioSocketChannel ch) throws Exception {
        ch.pipeline().addLast(new ClientResponses());
      }

    });

    return null;
  }

}
